home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.10 Oct 91 / Diamond WDEF Source / WorkDiamondWinds.c < prev   
Encoding:
C/C++ Source or Header  |  1991-04-24  |  10.5 KB  |  356 lines  |  [TEXT/KAHL]

  1. /* ==========================================================================
  2.  
  3. File: WorkDiamondWinds.c
  4. Function: Controls Diamond Windows.
  5. History: 7/4/90  &  8/26/90 - 1/16/91  &  2/15/91  &  4/15/91 - 4/22/91 : Marz. 
  6.  
  7. This file contains additional code illustrating the appropriate methodology for
  8. operating Diamond Windows.
  9.  
  10. ============================================================================= */
  11.  
  12. #include        "WindowMgr.h"
  13. #include        "DiamondDef.h"
  14.  
  15.  
  16. #define            NO_VARIATION                        0
  17. #define            wJUST_DRAGGED                        50
  18. #define            wNEW_TITLE                            51
  19.  
  20. #define            FLUSH_EVENTS                        0
  21. #define            VISIBLE                                TRUE
  22. #define            DIAMOND_DOC_PROC_PLUS_ZOOM            16008
  23. #define            NO_GROW_DIAMOND_PROC                16012
  24. #define            PLACE_IN_FRONT                        -1L
  25. #define            GO_AWAY_BOX                            TRUE
  26. #define            NULL_REF_NUM                        0
  27.  
  28.  
  29. typedef struct ZoomInfo    {
  30.     short                top;
  31.     short                midX;
  32.     short                length;
  33. } ZoomInfo;
  34.  
  35.  
  36. EventRecord            theEvent;
  37.  
  38. /* ========================================================================= */
  39.  
  40.  
  41. void   ZoomDiamondFrame(theWindow, expand)
  42. WindowPeek        theWindow;
  43. Boolean            expand;
  44. {
  45. /*    This function expands or shrinks a series of diamonds around the About
  46. Diamond when it is being Zoomed.  It's a very nice effect because it takes the
  47. user's mind off how long it's taking her or his window's contents to be redrawn
  48. and it also it looks cool.
  49. ****************************** Acknowledgement***********************************
  50.     I found a routine for drawing zoom indicator lines around windows in the
  51. Febuary 1987 issue of MacTutor.  I modified the original code written by Jean
  52. Decombe so that it would work well with diamond shaped windows and optimized it
  53. a touch by performing all division operations as bit shifts, using the Line()
  54. command instead of LineTo(), and by using the % {mod} function to reduce the
  55. number of necessary storage areas {normally rectangles, ZoomInfos in this case}.
  56. */
  57. GrafPtr        savedPort, deskPort;
  58. Rect        startRect, endRect, zoomRect;
  59. long        unit;
  60. short        index, topDiff, leftDiff, bottomDiff, rightDiff;
  61. ZoomInfo    zoomSpot[4], holder;
  62.  
  63.     startRect = ((WStateData*) *(theWindow->dataHandle))->stdState;
  64.     endRect = ((WStateData*) *(theWindow->dataHandle))->userState;
  65.     InsetRect(&startRect, -26, -26);
  66.     InsetRect(&endRect, -26, -26);
  67.     if (expand)
  68.     {
  69.         zoomRect = startRect;
  70.         startRect = endRect;
  71.         endRect = zoomRect;
  72.     }
  73.     topDiff = endRect.top - startRect.top;
  74.     leftDiff = endRect.left - startRect.left;
  75.     bottomDiff = endRect.bottom - startRect.bottom;
  76.     rightDiff = endRect.right - startRect.right;
  77.     GetPort(&savedPort);
  78.     GetWMgrPort(&deskPort);
  79.     InitPort(deskPort);
  80.     PenMode(notPatXor);
  81.     PenPat(&white);
  82.     for (index = 0; index <= 20; index ++)
  83.     {
  84.         if (index >= 4)
  85.         {    
  86.             holder = zoomSpot[index % 4];
  87.             MoveTo(holder.midX, holder.top);
  88.             Line(holder.length, holder.length);
  89.             Line(-holder.length, holder.length);
  90.             Line(-holder.length, -holder.length);
  91.             Line(holder.length, -holder.length);
  92.         }
  93.         if (index <= 16)
  94.         {
  95.             zoomRect = startRect;
  96.             unit = ((expand ? index + 1: 33 - index) * index) >> 1;
  97.             zoomRect.top += (unit * topDiff) >> 7;
  98.             zoomRect.left += (unit * leftDiff) >> 7;
  99.     /* zoomRect.bottom never needs to be adjusted because diamond shaped windows
  100.     grow in the horizontal and vertical directions at the same rate.
  101.     */
  102.             zoomRect.right += (unit * rightDiff) >> 7;
  103.             holder.top = zoomRect.top;
  104.             holder.midX = (zoomRect.right + zoomRect.left) >> 1;
  105.             holder.length = (zoomRect.right - zoomRect.left) >> 1;
  106.                 MoveTo(holder.midX, holder.top);
  107.                 Line(holder.length, holder.length);
  108.                 Line(-holder.length, holder.length);
  109.                 Line(-holder.length, -holder.length);
  110.                 Line(holder.length, -holder.length);
  111.             zoomSpot[index % 4] = holder;
  112.         }
  113.     }
  114.     PenMode(patCopy);
  115.     PenPat(&black);
  116.     SetPort(savedPort);
  117. }
  118.  
  119.  
  120.  
  121. Boolean   DoMouseDown(thePart, theWindow)
  122. short        thePart;
  123. WindowPtr    theWindow;
  124. {
  125. /* Handles mouse clicks.  Returns TRUE if the window was clicked in its close
  126. box.
  127. */
  128. Boolean            disposedWindow = FALSE;
  129. Handle            wDefHdl;
  130. long            newSize;
  131. Rect            growRect, sizeRestrict, theRect;
  132. RgnHandle        theRgn, strucRectRgn;
  133. short            adjust, offset, currentSize;
  134. WindowPeek        windPkr;
  135.  
  136.     if (theWindow != NULL)
  137.          SetPort(theWindow);
  138.     switch(thePart)
  139.     {
  140.         case inDesk:
  141.          case inSysWindow:
  142.              SystemClick(&theEvent, theWindow);
  143.              break;
  144.          case inDrag:
  145.             windPkr = (WindowPeek) theWindow;
  146. /*    The Window Manger automatically calls WDEFs passing the wDraw message when
  147. part of a window is dragged back onscreen after having been offscreen.  This
  148. segment of code sets the dragged member of the DataRecord structure, if the WDEF
  149. is called the dragged member will be set to FALSE.  If it remains TRUE after the
  150. DragWindow() procedure has been executed then the window's regions need to be
  151. updated and the WDEF is called to achieve this.
  152.     All this is necessary because when a window is dragged offscreen and then
  153. back on, the WDEF must recalculate its regions BEFORE redrawing the window, so
  154. that the full visible portion of the window is redrawn.
  155. */
  156.             windPkr->titleWidth = TRUE;
  157.             DragWindow(theWindow, theEvent.where, &screenBits.bounds);
  158. /* The WDEF should only be called here when <dataRecord>dragged == FALSE.
  159. Otherwise the diamond window's regions would be recalculated twice {what a
  160. waste}.  The Diamond WDEF automatically sets <dataRecord>.dragged to FALSE when
  161. called with the wJUST_DRAGGED message.
  162. */
  163.             if (windPkr->titleWidth)
  164.             {
  165.                 wDefHdl = windPkr->windowDefProc;
  166.                  HLock(wDefHdl);
  167.                  CallPascalL(NO_VARIATION, windPkr, wJUST_DRAGGED, 0L, *wDefHdl);
  168.                  HUnlock(wDefHdl);
  169.              }
  170.             if (theWindow != FrontWindow())
  171.                 if (!(theEvent.modifiers & cmdKey))
  172.                     SelectWindow(theWindow);
  173.             break;
  174.         case inGrow:
  175.         /* The size restriction is actually 50 for the lower limit and 400 for
  176.         the upper limit.  However, due to the nature of Diamond Windows only
  177.         half these values are used.
  178.         */
  179.             growRect = theWindow->portRect;
  180.             currentSize = (growRect.right - growRect.left) >> 1;
  181.             sizeRestrict.top = sizeRestrict.left = currentSize + 28;
  182.             sizeRestrict.bottom = sizeRestrict.right = currentSize + 200;
  183.             newSize = GrowWindow(theWindow, theEvent.where, &sizeRestrict);
  184. /* adjust originally holds a value which is too large, again due to the rate at
  185. which diamond windows grow and shrink.  This value is ANDed with 0xFFFE to ensure
  186. that the resultant number is even.  The result must then be manipulated so that
  187. it corresponds to the actual new size the window should be.
  188. */
  189.             /* Only HiWord() because movement left or right is inconsequential.    */
  190.             adjust = HiWord(newSize) & MAKE_EVEN;
  191.             if ((adjust != 0) && (adjust != (currentSize << 1)))
  192.             {
  193.             /* in case the origin has been offset        */
  194.                 offset = (adjust - (growRect.right - growRect.left));
  195.                 LocalToGlobal(&topLeft(growRect));
  196.                 ShowHide(theWindow, FALSE);
  197.                 SizeWindow(theWindow, adjust + offset, adjust + offset, FALSE);
  198.                 MoveWindow(theWindow, growRect.left - offset, 
  199.                     growRect.top - offset, TRUE);
  200.                 ShowHide(theWindow, TRUE);
  201.             }
  202.             break;
  203.         case inGoAway:
  204.              if (TrackGoAway(theWindow, theEvent.where))
  205.              {
  206.                  DisposeWindow(theWindow);
  207.                  disposedWindow = TRUE;
  208.              }
  209.              break;
  210.          case inContent:
  211.              if (theWindow != FrontWindow())
  212.                  SelectWindow(theWindow);
  213.              break;
  214.          case inZoomIn:
  215.          case inZoomOut:
  216.              if (TrackBox(theWindow, theEvent.where, thePart))
  217.              {
  218.                 ZoomDiamondFrame((WindowPeek) theWindow, thePart == inZoomOut);
  219.                 ShowHide(theWindow, FALSE);
  220.                 ZoomWindow(theWindow, thePart, TRUE);
  221.                 ShowHide(theWindow, TRUE);
  222.             }
  223.             break;
  224.     }
  225.     return(disposedWindow);
  226. }
  227.  
  228.  
  229.  
  230. void    UpdateDiamond(theWindow)
  231. WindowPeek        theWindow;
  232. {
  233. Rect        rgnRect = {20, 10, 180, 190};
  234.  
  235.     PaintRect(&rgnRect);
  236. }
  237.  
  238.  
  239.  
  240. void    SetDiamondWTitle(theWindow, newTitle)
  241. Ptr            theWindow;
  242. Str255        newTitle;
  243. {
  244. /*    Use the following lines to change a diamond window's title.
  245. */
  246. Handle        wDefHdl;
  247.  
  248.     wDefHdl = ((WindowPeek) theWindow)->windowDefProc;
  249.      HLock(wDefHdl);
  250.     CallPascalL(0, theWindow, wNEW_TITLE, newTitle, *wDefHdl);
  251.      HUnlock(wDefHdl);
  252. }
  253.  
  254.  
  255.  
  256. void DiamondWindowTest()
  257. {
  258. /*    Operates diamond shaped windows demonstrating many of the WDEF's abilities.
  259. */
  260. GrafPtr            oldPort;
  261. Handle            wDefHdl;
  262. Rect            windRect = {50, 50, 215, 215}, theRect;
  263. short            openWindows, thePart;
  264. Str255            newTitle = "\pThe Only Window";
  265. WindowPtr        theWindow;
  266.  
  267.     NewWindow(NULL, &windRect, "\pDiamond Window", VISIBLE,
  268.         DIAMOND_DOC_PROC_PLUS_ZOOM, PLACE_IN_FRONT, GO_AWAY_BOX, NULL_REF_NUM);
  269. /* When you wish to define diamond windows from resource definitions, everything
  270. should be set up normally.  Then, once you are satisfied with the configuration,
  271. go back and add an offset to the procID member to reflect the use of a custom
  272. WDEF.  The offset is the ID number assigned to the WDEF multiplied by 16.  In
  273. this case the ID number was 1000, so the offset is (16 * 1000) or 16000.  However,
  274. DIAMOND_DOC_PROC_PLUS_ZOOM = 16008.  The additional 8 specifies that the window
  275. should have one of each of the following regions: grow, goAway, and zoom. 
  276. */
  277.     InsetRect(&windRect, -20, -40);      /* these will be equalized by the WDEF */
  278.     OffsetRect(&windRect, 130, 55);
  279.     NewWindow(NULL, &windRect, "\pAnother Diamond Window", VISIBLE,
  280.         NO_GROW_DIAMOND_PROC, PLACE_IN_FRONT, GO_AWAY_BOX, NULL_REF_NUM);
  281.     openWindows = 2;
  282.     do
  283.     {
  284.         WaitNextEvent(everyEvent, &theEvent, 0L, 0L);
  285.         theWindow = (WindowPtr) theEvent.message;
  286.         if (theWindow != NULL)
  287.             SetPort(theWindow);
  288.         switch(theEvent.what)
  289.         {
  290.             case mouseDown:
  291.                 thePart = FindWindow(theEvent.where, &theWindow);
  292.                 if (DoMouseDown(thePart, theWindow))
  293.                 {
  294.                     openWindows --;
  295.                     if (openWindows == 1)
  296.                     {
  297.                         theWindow = FrontWindow();
  298.                         SetDiamondWTitle(theWindow, newTitle);
  299.  /* Demostration of SetOrigin()                                            */                
  300.                          SetPort(theWindow);
  301.                          SetOrigin(-30, -50);
  302.                          windRect = theWindow->portRect;
  303.  /* Must also offset the clipRgn so that it corresponds with the new window
  304.  coordinates.
  305.  */
  306.                          if ( (**((DataRecordHdl) ((WindowPeek) theWindow)->
  307.                              dataHandle)).resizable)
  308.                              OffsetRgn(theWindow->clipRgn, -30, -50);
  309.                          else
  310.                              InsetRect(&windRect, -26, -26);
  311.                          EraseRect(&windRect);
  312.                          InvalRect(&windRect);
  313.                     }
  314.                 }
  315.                 break;
  316.             case activateEvt:
  317.             case updateEvt:
  318.                 GetPort(&oldPort);
  319.                 SetPort(theWindow);
  320.                 DrawGrowIcon(theWindow);
  321.                 BeginUpdate(theWindow);
  322.                     UpdateDiamond((WindowPeek) theWindow);
  323.                 EndUpdate(theWindow);
  324.                 SetPort(oldPort);
  325.                 break;
  326.         }
  327.     }
  328.     while (openWindows > 0);
  329. }
  330.  
  331.  
  332.  
  333. void main()
  334. {
  335. /*    Initializes the ToolBox and calls the window handling function.
  336. */
  337. Ptr            reservedMem;
  338. Rect        screenRect;
  339. short        index;
  340.  
  341.     MaxApplZone();
  342.     InitGraf(&thePort);
  343.     InitFonts();
  344.     InitWindows();
  345.     TEInit();
  346.     InitDialogs(NULL);
  347.     InitMenus();
  348.     FlushEvents(everyEvent, FLUSH_EVENTS);
  349.     InitCursor();
  350.     DiamondWindowTest();
  351.     ExitToShell();
  352. }
  353.  
  354.  
  355.  
  356.